// *************************************************************************************************
//
// MK3D Engine
// --------------------------------------
// Copyright (C) 2007-2011 Zeb (mailto: zebbey@gmail.com)
//
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// *************************************************************************************************

#ifndef __H_MK_ENTITY__
#define __H_MK_ENTITY__

#include "mk_aabb.h"

namespace MK3DE
{
	class CScene;
	class CSceneNode;
	class CCamera;

	enum ENTITY_RENDER_TYPE
	{
		ERT_SOLID,
		ERT_TRANSPARENT,
		ERT_WATER,

		ERT_MAX,
	};

	enum ENTITY_TYPE
	{
		ET_MODEL,
		ET_PARTICLE_SYSTEM,
		ET_SKY_BOX,
		ET_TERRAIN,
		ET_TERRAIN_REGION,
		ET_WATER,

		ET_MAX,
	};

	class MK3DE_API CEntity
	{
	public:
		CEntity(CScene* pScene);
		virtual ~CEntity();

		virtual ENTITY_RENDER_TYPE GetRenderType() = 0;
		virtual ENTITY_TYPE GetType() = 0;

		//! Update the entity
		/**
			\param dt : the delta time.
			\param bChanged : Whether the attached scene node's transformation is changed.
		*/
		virtual void Update(DWORD dt, BOOL bChanged);

		//! Render the entity.
		virtual void Render();

		//! Render the entity for shadow mapping.
		virtual void RenderShadow(const D3DXMATRIX& matViewProj, const D3DXMATRIX& matWrap);
		
		//! Update its axis align bounding box in world coordinate.
		virtual void UpdateWorldAABB();

		//! View-frustum culling.
		virtual void ViewFrustumCulling(CCamera* camera, std::vector<CEntity*>& vecEntity);

	public:
		//! Get the scene node which the entity attached to.
		CSceneNode* GetAttachedSceneNode() { return _sceneNode; }

		//! Get world axis align bounding box.
		AABB GetWorldAABB() { return _worldAABB; }

		//! Set the entity visible or not.
		void SetVisible(BOOL bVisible) { _bVisible = bVisible; }
		BOOL IsVisible() { return _bVisible; }

		//! Enable or disable shadow cast.
		void EnableShadowCast(BOOL bEnable) { _bShadowCast = bEnable; }
		BOOL GetShadowCast() { return _bShadowCast; }

		//! Enable or disable shadow receive.
		void EnableShadowReceive(BOOL bEnable) { _bShadowRecv = bEnable; }
		BOOL GetShadowReceive() { return _bShadowRecv; }

	public:
		/** internal method */
		virtual void _AttachSceneNode(CSceneNode* pNode);

	protected:
		CScene* _scene;
		CSceneNode* _sceneNode;

		AABB _localAABB;
		AABB _worldAABB;

		BOOL _bVisible;
		BOOL _bShadowCast;
		BOOL _bShadowRecv;
	};
}

#endif // __H_MK_ENTITY__